<?php

namespace app\controllers\admin;

use app\models\Loan;
use app\models\Material;
use app\models\Member;
use app\models\News;
use app\models\Product;
use app\models\User;
use Yii;
use app\models\QuarterSetting;
use app\models\search\QuarterSetting as QuarterSettingSearch;
use app\controllers\admin\BaseController;
use yii\base\UserException;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * QuarterSettingController implements the CRUD actions for QuarterSetting model.
 */
class QuarterSettingController extends BaseController {
    /**
     * @inheritdoc
     */
    public function behaviors() {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Lists all QuarterSetting models.
     * @return mixed
     */
    public function actionIndex() {
        $searchModel = new QuarterSettingSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Creates a new QuarterSetting model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate() {
        $model = new QuarterSetting();
        $last = QuarterSetting::find()->orderBy(['create_at'=>SORT_DESC])->one();
        if(!$model->start_at && $last) {
            $model->start_at = date('Y-m-d\TH:i', strtotime("$last->end_at +1minute"));
            $model->end_at = date('Y-m-d\TH:i', strtotime("$last->end_at +1hour"));
        }

        if (Yii::$app->request->isPost && $model->load(Yii::$app->request->post())) {
            $model->is_open = false;
            $model->is_close = true;
            $model->is_settle = false;
            if(!$model->validate()){
                return $this->render('create', [
                    'model' => $model,
                    'message' => '请填写开始和结束时间',
                ]);
            }
            if(QuarterSetting::find()->andWhere(['>','end_at',$model->start_at])->exists()){
                return $this->render('create', [
                    'model' => $model,
                    'message' => '只能添加新的财年，财年开始时间必须晚于之前的所有财年',
                ]);
            }
            if(strtotime($model->start_at) >= strtotime($model->end_at)){
                return $this->render('create', [
                    'model' => $model,
                    'message' => '结束时间必须晚于开始时间',
                ]);
            }
            $model->save();
            return $this->redirect(['index', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
                'message' => '',
            ]);
        }
    }

    public function actionOpen() {
        if(QuarterSetting::find()->andWhere(['is_settle'=>false,'is_open'=>true,])->exists()){
            throw new UserException('上一财年未结算，无法开启新的财年');
        }
        $model = QuarterSetting::find()->andWhere(['is_open'=>false,])->orderBy(['create_at'=>SORT_ASC])->one();
        if(!$model){
            throw new UserException('没有新的财年了');
        }

        $model->is_open = true;
        $model->is_close = false;
        $model->save();

        return $this->redirect(['index']);
    }

    public function actionOpennow() {
        $model = QuarterSetting::find()->andWhere(['is_open'=>false,'is_close'=>true,'is_settle'=>false,])->orderBy(['create_at'=>SORT_ASC])->one();
        if(!$model){
            throw new UserException('没有新的财年了');
        }

        $model->is_open = true;
        $model->is_close = false;
        $model->save();

        return $this->redirect(['index']);
    }

    public function actionClose() {
        $model = QuarterSetting::find()->andWhere(['is_open'=>true,'is_close'=>false,])->one();

        if(!$model){
            throw new UserException('找不到需要关闭的财年');
        }

        $model->is_open = false;
        $model->is_close = true;
        $this->transaction(function() use($model) {
            $model->save();
        });

        return $this->redirect(['index']);
    }

    public function actionSettle() {
        $model = QuarterSetting::find()->andWhere(['is_settle'=>false,'is_open'=>false,'is_close'=>true,])->one();

        if(!$model){
            throw new UserException('找不到需要结算的财年');
        }

        $model->is_settle = true;
        $this->transaction(function() use($model) {
            $this->settle();
            $model->save();
        });

        return $this->redirect(['index']);
    }

    // 财年结算
    public function settle() {
        /** @var User[] $producers */
        $producers = User::find()
            ->andWhere([
                'role' => User::ROLE_PRODUCER
            ])->each();
        foreach ($producers as $producer) {
            $producer->previous_netasset = $producer->current_netasset;
            $producer->material_inventory =
                (double)$producer->getUserMaterials()
                ->leftJoin(Material::tableName(), 'material.id=user_material.material_id')
                ->sum('storage_num * price');
            $producer->products_inventory =
                (double)$producer->getUserProducts()
                    ->leftJoin(Product::tableName(), 'product.id=user_product.product_id')
                    ->sum('num * material_cost');
            $producer->total_loan = (double)$producer->getLoans()->andWhere(['status'=>Loan::STATUS_AUTH])->sum('num + interest');
            $producer->current_netasset = (double)($producer->current_currency + $producer->material_inventory + $producer->products_inventory - $producer->total_loan);
            $producer->netasset_growth = $producer->previous_netasset>0 ? ($producer->current_netasset / $producer->previous_netasset - 1) : 1;
            $producer->tech_level = $producer->getProducts()->andWhere(['status'=>Product::STATUS_AUTH])->sum('material_cost') / $producer->start_currency * 100;
            $producer->save();
        }

        /** @var User[] $traders */
        $traders = User::find()
            ->andWhere([
                'role' => User::ROLE_TRADER
            ])->each();
        foreach ($traders as $trader) {
            $trader->previous_netasset = $trader->current_netasset;
            $trader->material_inventory =
                (double)$trader->getUserMaterials()
                    ->leftJoin(Material::tableName(), 'material.id=user_material.material_id')
                    ->sum('storage_num * price');
            $trader->products_inventory =
                (double)$trader->getUserProducts()
                    ->leftJoin(Product::tableName(), 'product.id=user_product.product_id')
                    ->sum('num * material_cost');
            $trader->total_loan = (double)$trader->getLoans()->andWhere(['status'=>Loan::STATUS_AUTH])->sum('num + interest');
            $trader->current_netasset = (double)($trader->current_currency + $trader->material_inventory + $trader->products_inventory - $trader->total_loan);
            $trader->netasset_growth = $trader->previous_netasset>0 ? ($trader->current_netasset / $trader->previous_netasset - 1) : 1;
            $trader->save();
        }

        /** @var User[] $govs */
        $govs = User::find()
            ->andWhere([
                'role' => User::ROLE_GOV
            ])->each();
        $totalReduce = 0;
        foreach ($govs as $gov) {
            $reduce = $gov->current_currency * 0.15;
            $totalReduce += $reduce;
            $this->logForUser($gov, '财年结算', $gov->id, -$reduce);
            $gov->previous_netasset = $gov->current_netasset;
            $gov->total_loan = (double)$gov->getLoans()->andWhere(['status'=>Loan::STATUS_AUTH])->sum('num + interest');
            $gov->current_netasset = (double)($gov->current_currency + $gov->total_loan);
            $gov->netasset_growth = $gov->previous_netasset>0 ? ($gov->current_netasset / $gov->previous_netasset - 1) : 1;
            $gov->save();
        }

        /** @var User[] $admins */
        $admins = User::find()
            ->andWhere([
                'role' => User::ROLE_ADMIN
            ])->each();
        foreach ($admins as $admin) {
            $this->logForUser($admin, '财年结算', $gov->id, $totalReduce);
        }

        /** @var Member[] $members */
        $members = Member::find()->each();
        foreach ($members as $member) {
            $member->deposit = round($member->deposit + $member->salary + $member->commission, 2);
            $member->commission = 0;
            $member->save();
            $this->logForUser($member->user, '财年结算 - 支付工资', $member->id, -($member->salary + $member->commission), true);
        }

        $users = User::find()
            ->andWhere(['role'=>[User::ROLE_PRODUCER,User::ROLE_TRADER,User::ROLE_GOV,]])
            ->orderBy(['country_id'=>SORT_ASC, 'role'=>SORT_DESC, ])
            ->each();
        $model = new News();
        $model->type = News::TYPE_NOTICE;
        $model->title = "财年结算报告";
        $this->layout = false;
        $model->content = $this->render('report', [
            'users' => $users,
        ]);
        $model->author_id = $admin->id;
        $model->time = date('Y-m-d H:i:s');
        $model->save();
        $this->log('财年结算报告', $model->id);
    }

    /**
     * Finds the QuarterSetting model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return QuarterSetting the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id) {
        if (($model = QuarterSetting::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('页面不存在');
        }
    }
}
